`include "PRV564Config.v"
`include "PRV564Define.v"
/*****************************************************************************************
 *    author : Jack's Team
 *    e-mail : 
 *    date   : 20210726
 *    desc   : Vostok564_top level entry, include PRV564_top and SFR registers
               This project is build by:
               Chen Yuheng
               Huang Junguang
               Hong Xiaoyu
               Liu Dingbang
               Pan Xingyu
               Ying Chengbing
               Zhou Cong
               
 *    version: 0000
 
 __  __                   __           __         
/\ \/\ \                 /\ \__       /\ \        
\ \ \ \ \    ___     ____\ \ ,_\   ___\ \ \/'\    
 \ \ \ \ \  / __`\  /',__\\ \ \/  / __`\ \ , <    
  \ \ \_/ \/\ \L\ \/\__, `\\ \ \_/\ \L\ \ \ \\`\  
   \ `\___/\ \____/\/\____/ \ \__\ \____/\ \_\ \_\
    `\/__/  \/___/  \/___/   \/__/\/___/  \/_/\/_/


    This is a 64bit RISC-V processor

   "I see Earth! It is so beautiful!"
                        —— Yuri Gagarin

**********************************************************************************************/
module Vostok564_top
(
//----------------------Global signal---------------------
    input wire                      clock,   //Core clock (PRV564 kernal's clock)
    input wire                      reset,   //Core reset, async
//----------------------interrupt-------------------------
    input wire                      io_interrupt,
//-----------------------AXI interface---------------------
    output wire [3:0]               io_master_awid,
    output wire [`PADR-1:0]    		io_master_awaddr,
    output wire [7:0]               io_master_awlen,
    output wire [2:0]               io_master_awsize,
    output wire [1:0]               io_master_awburst,
    output wire                     io_master_awvalid,
    input  wire                     io_master_awready,
//---------------------写数据通道-----------------------------
    output wire [`XLEN-1:0]  		io_master_wdata,
    output wire [7:0]  				io_master_wstrb,
    output wire                     io_master_wlast,
    output wire                     io_master_wvalid,
    input  wire                     io_master_wready,
//----------------------写回复通道-------------------------------	
    input  wire [3:0]               io_master_bid,
    input  wire [1:0]               io_master_bresp,
    input  wire                     io_master_bvalid,
    output wire                     io_master_bready,
//---------------------读地址通道-----------------------------------	
    output wire [3:0]               io_master_arid,
    output wire [`PADR-1:0]    		io_master_araddr,
    output wire [7:0]               io_master_arlen,
    output wire [2:0]               io_master_arsize,
    output wire [1:0]               io_master_arburst,
    output wire                     io_master_arvalid,
    input  wire                     io_master_arready,
//----------------------读数据通道----------------------------------
    input  wire [3:0]  io_master_rid,
    input  wire [`XLEN-1:0]  		io_master_rdata,
    input  wire [1:0]               io_master_rresp,
    input  wire                     io_master_rlast,
//  input  wire [RUSER_WIDTH-1:0]   i_AXI_ruser,
    input  wire                     io_master_rvalid,
    output wire                     io_master_rready
);
    wire                Core_SRST;                                  //经过同步电路同步之后的同步复位
//----------------------interrupt-------------------------
    wire [`XLEN-1:0]    Kernel_MTIMEi;
    wire                Kernel_MTIi, Kernel_MSIi;                   //Machine mode timer, software external interrupt
    wire                Kernel_SEIi;
//-----------------------FIB interface---------------------
    wire                ICache_FIB_WRENo,   DCache_FIB_WRENo;
    wire                ICache_FIB_REQo,    DCache_FIB_REQo;
    reg                 ICache_FIB_ACKi,    DCache_FIB_ACKi;
    wire [7:0]          ICache_FIB_IDo,     DCache_FIB_IDo;
    wire [7:0]          ICache_FIB_CMDo,    DCache_FIB_CMDo;
    wire [3:0]          ICache_FIB_BURSTo,  DCache_FIB_BURSTo;
    wire [3:0]          ICache_FIB_SIZEo,   DCache_FIB_SIZEo;
    wire [`PADR-1:0]    ICache_FIB_ADDRo,   DCache_FIB_ADDRo;    
    wire [`XLEN-1:0]    ICache_FIB_DATAo,   DCache_FIB_DATAo;
    //                  TLB FIB interface
    wire                ITLB_FIB_WRENo,     DTLB_FIB_WRENo;
    wire                ITLB_FIB_REQo,      DTLB_FIB_REQo;
    reg                 ITLB_FIB_ACKi,      DTLB_FIB_ACKi;
    wire [7:0]          ITLB_FIB_IDo,       DTLB_FIB_IDo;
    wire [7:0]          ITLB_FIB_CMDo,      DTLB_FIB_CMDo;
    wire [3:0]          ITLB_FIB_BURSTo,    DTLB_FIB_BURSTo;
    wire [3:0]          ITLB_FIB_SIZEo,     DTLB_FIB_SIZEo;
    wire [`PADR-1:0]    ITLB_FIB_ADDRo,     DTLB_FIB_ADDRo;    
    wire [`XLEN-1:0]    ITLB_FIB_DATAo,     DTLB_FIB_DATAo;

    wire [3:0]          FIB_select;
    //               FIB access port
    reg                 FIB_AQ_WREN;
    reg                 FIB_AQ_V;
    wire                FIB_AQ_FULL;
    reg [7:0]           FIB_AQ_ID;
    reg [7:0]           FIB_AQ_CMD;
    reg [3:0]           FIB_AQ_BURST;
    reg [3:0]           FIB_AQ_SIZE;
    reg [`PADR-1:0]     FIB_AQ_ADDR;
    reg [`XLEN-1:0]     FIB_AQ_DATA;
    //               FIB result port
    wire                FIB_RQ_V;
    wire [7:0]          FIB_RQ_ID;
    wire [7:0]          FIB_RQ_AXIID;
    wire [7:0]          FIB_RQ_RPL;
    wire [`XLEN-1:0]    FIB_RQ_DATA;
    //----------------------FIB2AXI bridge side FIB signal-----------------------
    wire                FIB2AXI_AQ_V,       FIB2AXI_AQ_ACK;
    wire [7:0]          FIB2AXI_AQ_ID,      FIB2AXI_AQ_CMD;
    wire [3:0]          FIB2AXI_AQ_BURST,   FIB2AXI_AQ_SIZE;
    wire [`XLEN-1:0]    FIB2AXI_AQ_DATA;
    wire [`PADR-1:0]    FIB2AXI_AQ_ADDR;
//----------------------------SFR interface------------------------------
    wire [`PADR-1:0]    SFRi_ADDR;
    wire [`XLEN-1:0]    SFRi_DATA,  SFRo_DATA;
    wire                SFRi_WR,    SFRi_CS;
assign FIB_RQ_ID=8'h00|FIB_RQ_AXIID;
reset_gen       RST_SYNC(
    .clk                        (clock),
    .rst_async                  (reset),
    .rst_sync                   (Core_SRST)
);

PRV564_top
#(
    .HART_ID        (8'h0)
    // ITLB_FIBID=8'h01,
    // DTLB_FIBID=8'h02,
    // ICACHE_FIBID=8'h03,
    // DCACHE_FIBID=8'h04,
    // L1I_VOL=16384,//in byte
    // L1I_WAYNUM=4,
    // L1D_VOL=32768,
    // L1D_WAYNUM=8
)PRV564_top(
    .GLB_CLKi                   (clock),
    .GLB_ARSTi                  (Core_SRST),
//----------------Flexible Interconnection Bus----------
    .ITLB_FIB_WRENo             (ITLB_FIB_WRENo), 
    .DTLB_FIB_WRENo             (DTLB_FIB_WRENo),
    .ITLB_FIB_REQo              (ITLB_FIB_REQo),  
    .DTLB_FIB_REQo              (DTLB_FIB_REQo),
    .ITLB_FIB_ACKi              (ITLB_FIB_ACKi),  
    .DTLB_FIB_ACKi              (DTLB_FIB_ACKi),
    .ITLB_FIB_FULLi             (FIB_AQ_FULL), 
    .DTLB_FIB_FULLi             (FIB_AQ_FULL),
    .ITLB_FIB_IDo               (ITLB_FIB_IDo),   
    .DTLB_FIB_IDo               (DTLB_FIB_IDo),
    .ITLB_FIB_CMDo              (ITLB_FIB_CMDo),  
    .DTLB_FIB_CMDo              (DTLB_FIB_CMDo),
    .ITLB_FIB_BURSTo            (ITLB_FIB_BURSTo),
    .DTLB_FIB_BURSTo            (DTLB_FIB_BURSTo),
    .ITLB_FIB_SIZEo             (ITLB_FIB_SIZEo), 
    .DTLB_FIB_SIZEo             (DTLB_FIB_SIZEo),
    .ITLB_FIB_ADDRo             (ITLB_FIB_ADDRo), 
    .DTLB_FIB_ADDRo             (DTLB_FIB_ADDRo),    
    .ITLB_FIB_DATAo             (ITLB_FIB_DATAo),
    .DTLB_FIB_DATAo             (DTLB_FIB_DATAo),
    //             FIB result port
    .ITLB_FIB_IDi               (FIB_RQ_ID),
    .DTLB_FIB_IDi               (FIB_RQ_ID),
    .ITLB_FIB_RPLi              (FIB_RQ_RPL),  
    .DTLB_FIB_RPLi              (FIB_RQ_RPL),
    .ITLB_FIB_Vi                (FIB_RQ_V),
    .DTLB_FIB_Vi                (FIB_RQ_V),
    .ITLB_FIB_DATAi             (FIB_RQ_DATA),
    .DTLB_FIB_DATAi             (FIB_RQ_DATA),
//CPU Cache FIB
    .ICache_FIB_WRENo           (ICache_FIB_WRENo), 
    .DCache_FIB_WRENo           (DCache_FIB_WRENo),
    .ICache_FIB_REQo            (ICache_FIB_REQo),  
    .DCache_FIB_REQo            (DCache_FIB_REQo),
    .ICache_FIB_ACKi            (ICache_FIB_ACKi),  
    .DCache_FIB_ACKi            (DCache_FIB_ACKi),
    .ICache_FIB_FULLi           (FIB_AQ_FULL),
    .DCache_FIB_FULLi           (FIB_AQ_FULL),
    .ICache_FIB_IDo             (ICache_FIB_IDo),
    .DCache_FIB_IDo             (DCache_FIB_IDo),
    .ICache_FIB_CMDo            (ICache_FIB_CMDo),
    .DCache_FIB_CMDo            (DCache_FIB_CMDo),
    .ICache_FIB_BURSTo          (ICache_FIB_BURSTo),
    .DCache_FIB_BURSTo          (DCache_FIB_BURSTo),
    .ICache_FIB_SIZEo           (ICache_FIB_SIZEo), 
    .DCache_FIB_SIZEo           (DCache_FIB_SIZEo),
    .ICache_FIB_ADDRo           (ICache_FIB_ADDRo), 
    .DCache_FIB_ADDRo           (DCache_FIB_ADDRo),    
    .ICache_FIB_DATAo           (ICache_FIB_DATAo), 
    .DCache_FIB_DATAo           (DCache_FIB_DATAo),
    //               FIB result port
    .ICache_FIB_IDi             (FIB_RQ_ID),
    .DCache_FIB_IDi             (FIB_RQ_ID),
    .ICache_FIB_RPLi            (FIB_RQ_RPL),
    .DCache_FIB_RPLi            (FIB_RQ_RPL),
    .ICache_FIB_Vi              (FIB_RQ_V),
    .DCache_FIB_Vi              (FIB_RQ_V),
    .ICache_FIB_DATAi           (FIB_RQ_DATA), 
    .DCache_FIB_DATAi           (FIB_RQ_DATA),
//---------------Interrupt signal-------------------------
    .Kernel_MTIi                (Kernel_MTIi),          //Machine mode timer interrupt
    .Kernel_MSIi                (Kernel_MSIi),          //Machine mode software interrupt
    .Kernel_MEIi                (io_interrupt),         //Machine mode ext interrupt, input from SoC
    .Kernel_SEIi                (1'b0),                 //Supervisior mode ext interrupt
    .Kernel_NMIPLi              (1'b0),                 //NO NMI is used!
    .Kernel_NMIEEi              (1'b0),
    .Kernel_NMIGi               (1'b0),
//--------------Machine mode timer-----------------------
    .Kernel_MTIMEi              (Kernel_MTIMEi)	        //Machine mode timer value in
);

//------------------------FIB bus arbtine----------------------
FIB_arb         FIB_arb
(
    .CLKi                       (clock),
    .ARSTi                      (Core_SRST),
//-------------FIB master request-------------------
    .Master_REQ                 ({DCache_FIB_REQo, ICache_FIB_REQo, DTLB_FIB_REQo, ITLB_FIB_REQo}),
    .Master_ACK                 (FIB_select)
);
always@(*)begin
    case(FIB_select)
        4'b0001 : begin
                    FIB_AQ_WREN = ITLB_FIB_WRENo;
                    FIB_AQ_V    = ITLB_FIB_WRENo;
                    FIB_AQ_ID   = ITLB_FIB_IDo;
                    FIB_AQ_CMD  = ITLB_FIB_CMDo;
                    FIB_AQ_BURST= ITLB_FIB_BURSTo;
                    FIB_AQ_SIZE = ITLB_FIB_SIZEo;
                    FIB_AQ_ADDR = ITLB_FIB_ADDRo;
                    FIB_AQ_DATA = ITLB_FIB_DATAo;
                    ITLB_FIB_ACKi= 1'b1;
                    DTLB_FIB_ACKi= 1'b0;
                    ICache_FIB_ACKi=1'b0;
                    DCache_FIB_ACKi=1'b0;
                 end
        4'b0010 : begin
                    FIB_AQ_WREN = DTLB_FIB_WRENo;
                    FIB_AQ_V    = DTLB_FIB_WRENo;
                    FIB_AQ_ID   = DTLB_FIB_IDo;
                    FIB_AQ_CMD  = DTLB_FIB_CMDo;
                    FIB_AQ_BURST= DTLB_FIB_BURSTo;
                    FIB_AQ_SIZE = DTLB_FIB_SIZEo;
                    FIB_AQ_ADDR = DTLB_FIB_ADDRo;
                    FIB_AQ_DATA = DTLB_FIB_DATAo;
                    ITLB_FIB_ACKi= 1'b0;
                    DTLB_FIB_ACKi= 1'b1;
                    ICache_FIB_ACKi=1'b0;
                    DCache_FIB_ACKi=1'b0;
                 end
        4'b0100 : begin
                    FIB_AQ_WREN = ICache_FIB_WRENo;
                    FIB_AQ_V    = ICache_FIB_WRENo;
                    FIB_AQ_ID   = ICache_FIB_IDo;
                    FIB_AQ_CMD  = ICache_FIB_CMDo;
                    FIB_AQ_BURST= ICache_FIB_BURSTo;
                    FIB_AQ_SIZE = ICache_FIB_SIZEo;
                    FIB_AQ_ADDR = ICache_FIB_ADDRo;
                    FIB_AQ_DATA = ICache_FIB_DATAo;
                    ITLB_FIB_ACKi= 1'b0;
                    DTLB_FIB_ACKi= 1'b0;
                    ICache_FIB_ACKi=1'b1;
                    DCache_FIB_ACKi=1'b0;
                 end
        4'b1000 : begin
                    FIB_AQ_WREN = DCache_FIB_WRENo;
                    FIB_AQ_V    = DCache_FIB_WRENo;
                    FIB_AQ_ID   = DCache_FIB_IDo;
                    FIB_AQ_CMD  = DCache_FIB_CMDo;
                    FIB_AQ_BURST= DCache_FIB_BURSTo;
                    FIB_AQ_SIZE = DCache_FIB_SIZEo;
                    FIB_AQ_ADDR = DCache_FIB_ADDRo;
                    FIB_AQ_DATA = DCache_FIB_DATAo;
                    ITLB_FIB_ACKi= 1'b0;
                    DTLB_FIB_ACKi= 1'b0;
                    ICache_FIB_ACKi=1'b0;
                    DCache_FIB_ACKi=1'b1;
                 end
        default: begin
                    FIB_AQ_WREN = 1'b0;
                    FIB_AQ_V    = 1'b0;
                    FIB_AQ_ID   = 'hx;
                    FIB_AQ_CMD  = 'hx;
                    FIB_AQ_BURST= 'hx;
                    FIB_AQ_SIZE = 'hx;
                    FIB_AQ_ADDR = 'hx;
                    FIB_AQ_DATA = 'hx;
                    ITLB_FIB_ACKi= 1'b0;
                    DTLB_FIB_ACKi= 1'b0;
                    ICache_FIB_ACKi=1'b0;
                    DCache_FIB_ACKi=1'b0;
                 end
    endcase
end
//------------------------SFR registers-------------------------------
// Note: SFR registers now have CLINT registers
//       more special function register will be added soon
SFR              SFR(
//----------------SFR Slave interface-------------------
    //       Global signal input
    .CLKi                       (clock),
    .ARSTi                      (Core_SRST),
    //        access from master
    .SFRi_ADDR                  ({32'h0000_0000,SFRi_ADDR}),
    .SFRi_DATA                  (SFRi_DATA),
    .SFRi_CS                    (SFRi_CS),
    .SFRi_WR                    (SFRi_WR),
    .SFRo_DATA                  (SFRo_DATA),
    //       
    .CLINT_MTI                  (Kernel_MTIi),
    .CLINT_MSI                  (Kernel_MSIi),
    .CLINT_MTIME                (Kernel_MTIMEi)
);
//-----------------------FIB Access FIFO----------------------
wire busfifo_empty;
assign FIB2AXI_AQ_V=(!busfifo_empty);
SyncFIFO_Bus #( .DWID(120), .DDEPTH(8))
BUSFIFO(
    .clk(clock),
    .rst(Core_SRST),
    .ren(FIB2AXI_AQ_ACK),
    .wen(FIB_AQ_WREN),
    .wdata({FIB_AQ_ID, FIB_AQ_CMD, FIB_AQ_BURST, FIB_AQ_SIZE, FIB_AQ_DATA, FIB_AQ_ADDR}),
    .rdata({FIB2AXI_AQ_ID, FIB2AXI_AQ_CMD, FIB2AXI_AQ_BURST, FIB2AXI_AQ_SIZE, FIB2AXI_AQ_DATA, FIB2AXI_AQ_ADDR}),
    .full(FIB_AQ_FULL),
    .empty(busfifo_empty)
);
//-----------------------FIB 2 AXI bridge---------------------
FIB2AXI #(
    .AXI_ID_WIDTH               (4),
    .AXI_ADDR_WID               (32)
)FIB2AXI(
    .CLKi                       (clock),
    .RSTi                       (Core_SRST),
//--------------------FIB interface----------------
//                 from AQ FIFO
    .FIBo_ACK                   (FIB2AXI_AQ_ACK),
    .FIBi_V                     (FIB2AXI_AQ_V),
    .FIBi_ID                    (FIB2AXI_AQ_ID),
    .FIBi_CMD                   (FIB2AXI_AQ_CMD),
    .FIBi_BURST                 (FIB2AXI_AQ_BURST),
    .FIBi_SIZE                  (FIB2AXI_AQ_SIZE),
    .FIBi_ADDR                  (FIB2AXI_AQ_ADDR),
    .FIBi_DATA                  (FIB2AXI_AQ_DATA),
    //            reply to master
    .FIBo_ID                    (FIB_RQ_AXIID),
    .FIBo_RPL                   (FIB_RQ_RPL),
    .FIBo_WREN                  (FIB_RQ_V),
    .FIBi_FULL                  (1'b0),
//  .FIBo_ADDR,
    .FIBo_DATA                  (FIB_RQ_DATA),
//------------------SFR interface------------------------
    .FIBo_SFRi_ADDR             (SFRi_ADDR),
    .FIBo_SFRi_DATA             (SFRi_DATA),
    .FIBo_SFRi_CS               (SFRi_CS),
    .FIBo_SFRi_WR               (SFRi_WR),
    .FIBi_SFRo_DATA             (SFRo_DATA),
//-------------------AXI interface---------------------
//-------------------写地址通道-----------------------
    .FIBo_AXI_awid              (io_master_awid),
    .FIBo_AXI_awaddr            (io_master_awaddr),
    .FIBo_AXI_awlen             (io_master_awlen),
    .FIBo_AXI_awsize            (io_master_awsize),
     .FIBo_AXI_awburst           (io_master_awburst),
    // .FIBo_AXI_awlock            (o_AXI_awlock),
    // .FIBo_AXI_awcache           (o_AXI_awcache),
    // .FIBo_AXI_awprot            (o_AXI_awprot),
    // .FIBo_AXI_awqos             (o_AXI_awqos),
    // .FIBo_AXI_awregion          (o_AXI_awregion),
//  output reg [AWUSER_WIDTH-1:0]  	FIBo_AXI_awuser,
    .FIBo_AXI_awvalid           (io_master_awvalid),
    .FIBi_AXI_awready           (io_master_awready),
//---------------------写数据通道-----------------------------
    .FIBo_AXI_wdata             (io_master_wdata),
    .FIBo_AXI_wstrb             (io_master_wstrb),
    .FIBo_AXI_wlast             (io_master_wlast),
    .FIBo_AXI_wvalid            (io_master_wvalid),
    .FIBi_AXI_wready            (io_master_wready),
//----------------------写回复通道-------------------------------	
    .FIBi_AXI_bid               (io_master_bid),
    .FIBi_AXI_bresp             (io_master_bresp),
    .FIBi_AXI_bvalid            (io_master_bvalid),
    .FIBo_AXI_bready            (io_master_bready),
//---------------------读地址通道-----------------------------------	
    .FIBo_AXI_arid              (io_master_arid),
    .FIBo_AXI_araddr            (io_master_araddr),
    .FIBo_AXI_arlen             (io_master_arlen),
    .FIBo_AXI_arsize            (io_master_arsize),
    .FIBo_AXI_arburst           (io_master_arburst),
    // .FIBo_AXI_arlock            (o_AXI_arlock),
    // .FIBo_AXI_arcache           (o_AXI_arcache),
    // .FIBo_AXI_arprot            (o_AXI_arprot),
    // .FIBo_AXI_arqos             (o_AXI_arqos),
    // .FIBo_AXI_arregion          (o_AXI_arregion),
    .FIBo_AXI_arvalid           (io_master_arvalid),
    .FIBi_AXI_arready           (io_master_arready),
//----------------------读数据通道----------------------------------
    .FIBi_AXI_rid               (io_master_rid),
    .FIBi_AXI_rdata             (io_master_rdata),
    .FIBi_AXI_rresp             (io_master_rresp),
    .FIBi_AXI_rlast             (io_master_rlast),
    .FIBi_AXI_rvalid            (io_master_rvalid),
    .FIBo_AXI_rready            (io_master_rready)
);
//-------------------FIB bus monitor----------------
// TODO remove this block before send it to ASIC flow
`ifdef STUCK_AUTO_STOP
reg [63:0] bus_stuck_cnt;
always@(posedge clock)begin
    if(FIB2AXI_AQ_V)begin
        if(FIB2AXI_AQ_ACK)begin
            bus_stuck_cnt <= 0;
        end
        else begin
            bus_stuck_cnt <= bus_stuck_cnt + 1;
        end
    end
    if(bus_stuck_cnt > 4000)begin
        $display("FIB BUS ERROR : FIB AQ has no ACK from bridge in 4000 cycle, stop simulate");
        $finish;
    end
end
`endif 

endmodule